﻿using System;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace Peter.TFS
{
   /// <summary>
   /// Represents a connection to a TFS server.
   /// </summary>
   public class TfsBase : IDisposable
   {
      #region Fields

      /// <summary>
      /// Occurs when the server is connected.
      /// </summary>
      public event EventHandler Connected;

      /// <summary>
      /// Reference to the TFS Server.
      /// </summary>
      private TfsTeamProjectCollection m_TfsConn;

      private WorkItemStore m_WorkItemStore;
      private VersionControlServer m_VersionControlServer;
      private IBuildServer m_BuildServer;

      #endregion

      #region Setup

      /// <summary>
      /// Initializes a new TFS connection.
      /// </summary>
      public TfsBase ()
      {
         this.m_TfsConn = null;
      }

      /// <summary>
      /// Connects the object to the TFS Server and retrieve a reference to the services provided by the server.
      /// </summary>
      /// <param name="server">Name of the computer that offers TFS services.</param>
      /// <returns>True if conncted successfully.</returns>
      public void Connect (string server)
      {
         this.Connect (server, string.Empty);
      }

      /// <summary>
      /// Connects the object to the TFS Server and retrieve a reference to the services provided by the server.
      /// </summary>
      /// <param name="server">Name of the computer that offers TFS services.</param>
      /// <param name="tfsDirectory">Directory on server where TFS abides.</param>
      /// <returns>True if conncted successfully.</returns>
      public void Connect (string server, string tfsDirectory)
      {
         this.Connect (server, TfsConsts.DEFAULT_TFS_PORT, tfsDirectory);
      }

      /// <summary>
      /// Connects the object to the TFS Server and retrieve a reference to the services provided by the server.
      /// </summary>
      /// <param name="server">Name of the computer that offers TFS services.</param>
      /// <param name="port">Port TFS is using (default is 8080).</param>
      /// <param name="tfsDirectory">Directory on server where TFS abides.</param>
      /// <returns>True if conncted successfully.</returns>
      public void Connect (string server, string port, string tfsDirectory)
      {
         string serverUri = string.Format ("http://{0}:{1}/{2}", server, port, tfsDirectory);
         this.m_TfsConn = new TfsTeamProjectCollection (new Uri (serverUri));
         this.m_TfsConn.Authenticate ();
         if (this.Connected != null) this.Connected (this, new EventArgs ());
      }

      #endregion

      #region Properties

      /// <summary>
      /// Reference to the Work Item Store
      /// </summary>
      public WorkItemStore WorkItemStore
      {
         get
         {
            if (this.m_TfsConn == null)
               throw new InvalidOperationException ("TFS Server is null.");

            return this.m_WorkItemStore ?? (this.m_WorkItemStore = this.m_TfsConn.GetService<WorkItemStore> ());
         }
      }

      /// <summary>
      /// Gets or Sets the Version Control Server.
      /// </summary>
      public VersionControlServer VersionControl
      {
         get
         {
            if (this.m_TfsConn == null)
               throw new InvalidOperationException ("TFS Server is null.");

            return this.m_VersionControlServer ??
                   (this.m_VersionControlServer = this.m_TfsConn.GetService<VersionControlServer> ());
         }
      }

      /// <summary>
      /// Gets or Sets the Group Secruity Service.
      /// </summary>
      public IBuildServer BuildService
      {
         get
         {
            if (this.m_TfsConn == null)
               throw new InvalidOperationException ("TFS Server is null.");

            return this.m_BuildServer ?? (this.m_BuildServer = this.m_TfsConn.GetService<IBuildServer> ());
         }
      }

      /// <summary>
      /// Gets the Display name of the current user.
      /// </summary>
      public string UserDisplayName
      {
         get
         {
            return m_TfsConn.AuthorizedIdentity.DisplayName;
         }
      }

      /// <summary>
      /// Gets or Sets the Name of the TFS Server.
      /// </summary>
      public string ServerName
      {
         get
         {
            string server = string.Empty;
            if (this.m_TfsConn != null)
               server = this.m_TfsConn.Name;
            return server;
         }
      }

      /// <summary>
      /// Gets an array of all the Projects on TFS.
      /// </summary>
      public TeamProject[] TeamProjects
      {
         get { return this.VersionControl.GetAllTeamProjects (true); }
      }

      #endregion

      #region Methods

      /// <summary>
      /// Gets the service for the given type.
      /// </summary>
      /// <typeparam name="T">Type of service to get.</typeparam>
      /// <returns>Requested service, null if it does not exist.</returns>
      public T GetService<T> ()
      {
         return this.m_TfsConn.GetService<T> ();
      }

      #endregion

      #region IDisposable Members

      /// <summary>
      /// Cleans up any resources.
      /// </summary>
      public void Dispose ()
      {
         this.Disconnect ();
      }

      /// <summary>
      /// Disconnects from the TFS Server.
      /// </summary>
      public void Disconnect ()
      {
         if (m_TfsConn != null)
         {
            this.m_BuildServer = null;
            this.m_VersionControlServer = null;
            this.m_WorkItemStore = null;
            this.m_TfsConn.Dispose ();
            this.m_TfsConn = null;
         }
      }

      #endregion
   }
}
